package com.cwx.mychat.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cwx.mychat.entity.constant.CodeConstant;
import com.cwx.mychat.entity.constant.SysSettingConstant;
import com.cwx.mychat.entity.dto.TokenUserInfoDto;
import com.cwx.mychat.entity.enums.*;
import com.cwx.mychat.entity.po.*;
import com.cwx.mychat.entity.vo.*;
import com.cwx.mychat.exception.BusinessException;
import com.cwx.mychat.mappers.*;
import com.cwx.mychat.service.UserContactService;
import com.cwx.mychat.utils.R;
import com.cwx.mychat.utils.common.CommonUtil;
import com.cwx.mychat.utils.redis.RedisComponent;
import com.cwx.mychat.utils.stringUtils.StringUtil;
import com.cwx.mychat.websocket.message.SendMessageHandler;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

@Service
@Slf4j
public class UserContactServiceImpl extends ServiceImpl<UserContactMapper, UserContact> implements UserContactService {

    @Autowired
    private RedisComponent redisComponent;


    @Autowired
    private ChatSessionMapper chatSessionMapper;

    @Autowired
    private ChatSessionUserMapper chatSessionUserMapper;

    @Autowired
    private ChatMessageMapper chatMessageMapper;

    @Autowired
    private UserInfoMapper userInfoMapper;

    @Autowired
    private GroupInfoMapper groupInfoMapper;

    @Autowired
    private GroupNoticeMapper groupNoticeMapper;

    @Autowired
    private UserContactCategoryMapper userContactCategoryMapper;

    @Autowired
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addContactRobot(String userId, String nickName) {
        Date date = new Date();
        SysSettingConstant sysSetting = redisComponent.getSysSetting();
        String robotUid = sysSetting.getRobotUid();
        String robotNickName = sysSetting.getRobotNickName();
        String robotWelcome = sysSetting.getRobotWelcome();
        String sendMessage = StringUtil.cleanHtmlTag(robotWelcome);
        //增加机器人好友
        UserContact userContact = new UserContact();
        userContact.setUserId(userId);
        userContact.setContactId(robotUid);
        userContact.setContactType(UserContactTypeEnum.USER.getType());
        userContact.setCreateTime(date);
        userContact.setLastUpdateTime(date);
        userContact.setStatus(UserContactStatusEnum.FRIEND.getStatus());
        this.baseMapper.insert(userContact);
        //增加会话信息
        String sessionId = CommonUtil.getChatSessionIdUser(new String[]{userId, robotUid});
        ChatSession chatSession = new ChatSession();
        chatSession.setLastMessage(sendMessage);
        chatSession.setLastReceiveTime(date.getTime());
        chatSession.setSessionId(sessionId);
        chatSession.setCreateTime(date);
        chatSessionMapper.insert(chatSession);
        //增加会话联系人信息
        ChatSessionUser chatSessionUser = new ChatSessionUser();
        chatSessionUser.setUserId(userId);
        chatSessionUser.setContactId(robotUid);
        chatSessionUser.setContactName(robotNickName);
        chatSessionUser.setSessionId(sessionId);
        chatSessionUser.setNickName(nickName);
        chatSessionUserMapper.insert(chatSessionUser);
        //增加聊天信息
        ChatMessage chatMessage = new ChatMessage();
        chatMessage.setSessionId(sessionId);
        chatMessage.setMessageType(MessageTypeEnum.CHAT.getType());
        chatMessage.setMessageContent(sendMessage);
        chatMessage.setSendUserId(robotUid);
        chatMessage.setSendUserNickName(robotNickName);
        chatMessage.setSendTime(date.getTime());
        chatMessage.setContactId(userId);
        chatMessage.setContactType(UserContactTypeEnum.USER.getType());
        chatMessage.setStatus(MessageStatusEnum.SEND.getStatus());
        chatMessage.setCreateTime(date);
        chatMessageMapper.insert(chatMessage);
    }

    @Override
    public List<UserContact> selectContact(UserInfo userInfo) {
        List<UserContact> userContactList = this.baseMapper.selectContactList(userInfo.getUserId());
        return userContactList;
    }

    @Override
    public R getAllContactForUser(String userId) {
        UserCategoryVo userCategoryVo = new UserCategoryVo();
        List<String> contactIds = new ArrayList<>();
        List<UserContact> userContactList = this.baseMapper.selectList(new LambdaQueryWrapper<UserContact>().select(UserContact::getContactId, UserContact::getUserId, UserContact::getRemark)
                .eq(UserContact::getUserId, userId)
                .or()
                .eq(UserContact::getContactId, userId));
        userContactList.forEach(item -> {
            if(item.getUserId().startsWith(UserContactTypeEnum.USER.getPrefix()) && item.getContactId().startsWith(UserContactTypeEnum.USER.getPrefix())){
                if(item.getContactId().equals(userId)){
                    contactIds.add(item.getUserId());
                }else{
                    contactIds.add(item.getContactId());
                }
            }
        });
        //查询所有昵称
        List<UserInfoVO> userInfos = userInfoMapper.selectAll(contactIds);
        //添加备注
        try {
            getRemark(userContactList, userInfos);
        } catch (Exception e) {
            log.error("添加备注失败", e);
        }
        //查询所有分组
        Map<String, List<UserInfoVO>> userCategoryMap = new HashMap<>();
        List<UserContactCategory> userCategories = userContactCategoryMapper.selectList(new LambdaQueryWrapper<UserContactCategory>()
                .eq(UserContactCategory::getUserId, userId)
                .eq(UserContactCategory::getType, UserContactTypeEnum.USER.getType())
                .orderByAsc(UserContactCategory::getSort));
        //查询分组下的用户
        userCategories.forEach(item -> {
            List<String> userIds = CommonUtil.convertJsonToList(item.getUserCategory(), String.class);
            if(userIds != null){
                //通过userIds查找userInfo
                List<UserInfoVO> userInfoVOS = userInfos.stream().filter(userInfoVO -> userIds.contains(userInfoVO.getUserId())).toList();
                userCategoryMap.put(item.getCategoryName() + "-" + item.getCategoryId() + "-" + item.getSort(), userInfoVOS);
            }
        });
        userCategoryVo.setAllFriends(userInfos);
        userCategoryVo.setCategoryFriends(userCategoryMap);
        return R.ok().put(CodeConstant.RESULT_MSG, userCategoryVo);
    }

    private void getRemark(List<UserContact> userContactList, List<UserInfoVO> userInfos) throws Exception {
        List<Map<String, Object>> errors = new ArrayList<>();
        userInfos.forEach(item -> {
            userContactList.forEach(remark -> {
                try{
                    if(remark.getUserId().equals(item.getUserId()) || remark.getContactId().equals(item.getUserId())){
                        String contactRemark = remark.getRemark();
                        //转化json
                        if(!StringUtil.isEmpty(contactRemark)){
                            ObjectMapper objectMapper = new ObjectMapper();
                            List<HashMap<String, Object>> remarkListMap = objectMapper.readValue(contactRemark, List.class);
                            if(remarkListMap.size() != 2){
                                throw new BusinessException(ExceptionBizCodeEnum.UPDATE_FAILED);
                            }
                            //查看当前用户
                            HashMap<String, Object> userMap = remarkListMap.get(0);
                            HashMap<String, Object> contactMap = remarkListMap.get(1);
                            if(item.getUserId().equals(remark.getUserId()) && userMap.get("userId").toString().equals(item.getUserId())){
                                item.setRemark(userMap.get("remark").toString());
                            }
                            if(item.getUserId().equals(remark.getContactId()) && contactMap.get("contactId").toString().equals(item.getUserId())){
                                item.setRemark(contactMap.get("remark").toString());
                            }
                        }
                    }
                }catch (Exception e){
                    //收集异常
                    log.error("失败", e);
                    Map<String, Object> map = new HashMap<>();
                    map.put("message", e.getMessage());
                    errors.add(map);
                }
            });
        });
        // 如果有错误，抛出一个新的异常，包含所有错误信息
        if (!errors.isEmpty()) {
            throw new Exception("在增加备注时发生错误: " + errors.toString());
        }
    }

    @Override
    public R getAllContactForGroup(String userId) {
        //联系人列表的关于群的信息只存储了管理员的与群的关系
        //异步查询任务
        GroupCategoryVo groupCategoryVo = new GroupCategoryVo();
        //异步查询我创建的群聊
        CompletableFuture<Void> myCreateGroupTask = CompletableFuture.runAsync(() -> {
           try{
               //查询我创建的群聊
               List<GroupInfo> groupInfos = this.groupInfoMapper.selectList(new LambdaQueryWrapper<GroupInfo>()
                       .eq(GroupInfo::getGroupOwnerId, userId)
                       .eq(GroupInfo::getStatus, 1));
               groupCategoryVo.setMyCreateGroup(groupInfos);
           }catch (Exception e){
               groupCategoryVo.setMyCreateGroup(null);
               log.error("我创建的群聊查询失败", e);
           }
        }, threadPoolTaskExecutor);

        //异步查询我加入的群聊
        CompletableFuture<Void> myJoinGroupTask = CompletableFuture.runAsync(() -> {
            try{
                //查询我加入的群聊
                List<UserContact> userContactList = this.baseMapper.selectList(new LambdaQueryWrapper<UserContact>()
                        .select(UserContact::getUserId, UserContact::getContactId)
                        .eq(UserContact::getStatus, 1)
                        .like(UserContact::getContactId, UserContactTypeEnum.GROUP.getPrefix() + "%")
                        .eq(UserContact::getUserId, userId));
                List<String> joinGroupIds = userContactList.stream().map(UserContact::getContactId).collect(Collectors.toList());
                List<GroupInfo> groupInfos = new ArrayList<>();
                if(joinGroupIds.size() > 0) {
                    groupInfos = this.groupInfoMapper.selectList(new LambdaQueryWrapper<GroupInfo>()
                            .in(GroupInfo::getGroupId, joinGroupIds)
                            .eq(GroupInfo::getStatus, 1)
                            .ne(GroupInfo::getGroupOwnerId, userId));
                }
                List<GroupInfoVo> groupInfoVos = new ArrayList<>();
                //设置备注
                groupInfos.forEach(item -> {
                    GroupInfoVo groupInfoVo = new GroupInfoVo();
                    BeanUtils.copyProperties(item, groupInfoVo);
                    userContactList.forEach(contact -> {
                        if(contact.getContactId().equals(item.getGroupId())){
                            groupInfoVo.setRemark(getRemark(contact.getContactId(), contact.getRemark()));
                        }
                    });
                    groupInfoVos.add(groupInfoVo);
                });
                groupCategoryVo.setMyJoinGroup(groupInfoVos);
            }catch (Exception e){
                groupCategoryVo.setMyJoinGroup(null);
                log.error("我加入的群聊查询失败", e);
            }
        });

        //异步查询我管理的群聊
        CompletableFuture<Void> myManagerGroupTask = CompletableFuture.runAsync(() -> {
            try {
                List<ChatSessionUser> chatSessionUserList = this.chatSessionUserMapper.selectList(new LambdaQueryWrapper<ChatSessionUser>()
                        .select(ChatSessionUser::getUserId, ChatSessionUser::getContactId)
                        .eq(ChatSessionUser::getIsAdmin, GroupAdminTypeEnum.IS_ADMIN.getStatus())
                        .eq(ChatSessionUser::getUserId, userId)
                        .like(ChatSessionUser::getContactId, UserContactTypeEnum.GROUP.getPrefix() + "%"));
                List<String> managesGroupIds = chatSessionUserList.stream().map(ChatSessionUser::getContactId).collect(Collectors.toList());
                List<GroupInfoVo> groupInfos = new ArrayList<>();
                if(managesGroupIds.size() > 0){
                    groupInfos = this.groupInfoMapper.selectByIds(managesGroupIds, userId);
                }
                //设置备注
                groupInfos.forEach(item -> {
                    System.out.println(item);
                   item.setRemark(getRemark(item.getGroupId(), item.getRemark()));
                });
                groupCategoryVo.setMyManageGroup(groupInfos);
            } catch (Exception e) {
                groupCategoryVo.setMyManageGroup(null);
                log.error("我管理的群聊查询失败", e);
            }
        });
        //异步查询分组，以及分组下的群聊
        CompletableFuture<Void> myCreateCategoryGroupTask = CompletableFuture.runAsync(() -> {
            try{
                //查询分组
                Map<String, List<GroupInfo>> groupCategoryMap = new HashMap<>();
                List<UserContactCategory> userContactCategories = this.userContactCategoryMapper.selectList(new LambdaQueryWrapper<UserContactCategory>()
                        .eq(UserContactCategory::getUserId, userId)
                        .eq(UserContactCategory::getType, UserContactTypeEnum.GROUP.getType())
                        .orderByAsc(UserContactCategory::getSort));
                //查询分组下的群聊
                List<String> groupList = new ArrayList<>();
                userContactCategories.forEach(userContactCategory -> {
                    List<String> groups = CommonUtil.convertJsonToList(userContactCategory.getGroupCategory(), String.class);
                    if (groups != null) {
                        groupList.addAll(groups);
                        groupCategoryMap.put(userContactCategory.getCategoryName() + "-" + userContactCategory.getCategoryId() + "-" + userContactCategory.getSort(), new ArrayList<>());
                    }
                });
                //去重
                List<String> groupDistinctList = groupList.stream().distinct().toList();
                //查询群聊信息
                List<GroupInfoVo> groupInfos = this.groupInfoMapper.selectByIds(groupDistinctList, userId);
                groupInfos.forEach(groupInfo -> {
                    System.out.println(groupInfo);
                    groupInfo.setRemark(getRemark(groupInfo.getGroupId(), groupInfo.getRemark()));
                });
                //重新组装
                userContactCategories.forEach(userContactCategory -> {
                    if(groupCategoryMap.containsKey(userContactCategory.getCategoryName() + "-" + userContactCategory.getCategoryId() + "-" + userContactCategory.getSort())){
                        groupCategoryMap.get(userContactCategory.getCategoryName() + "-" + userContactCategory.getCategoryId() + "-" + userContactCategory.getSort())
                                                .addAll(groupInfos.stream().filter(groupInfo -> Objects.requireNonNull(CommonUtil.convertJsonToList(userContactCategory.getGroupCategory(), String.class))
                                                .contains(groupInfo.getGroupId())).toList());
                    }
                });
                groupCategoryVo.setMyCategoryGroup(groupCategoryMap);
            }catch (Exception e){
                groupCategoryVo.setMyCategoryGroup(null);
                log.error("我创建的分组下的群聊查询失败", e);
            }
        });
        try {
            CompletableFuture.allOf( myCreateGroupTask, myJoinGroupTask, myManagerGroupTask, myCreateCategoryGroupTask).get();
            return R.ok().put(CodeConstant.RESULT_MSG, groupCategoryVo);
        } catch (Exception e) {
            throw new RuntimeException(ExceptionBizCodeEnum.GROUP_SELECT_FAILED.getMsg());
        }
    }

    @Override
    public R updateRemark(String contactId, String remark) throws BusinessException {
        //获取当前userId
        TokenUserInfoDto tokenUserInfoDto = CommonUtil.getSecurityContext();
        //根据userId查询UserContact查询是主动加好友还是被动加好友
        UserContact userContact = this.baseMapper.selectOne(new LambdaQueryWrapper<UserContact>()
                .eq(UserContact::getUserId, tokenUserInfoDto.getUserId())
                .eq(UserContact::getContactId, contactId)
                .or()
                .eq(UserContact::getContactId, tokenUserInfoDto.getUserId())
                .eq(UserContact::getUserId, contactId));
        if(userContact == null){
            log.error("未查询到好友...");
            throw new BusinessException(ExceptionBizCodeEnum.UPDATE_FAILED);
        }
        if(!userContact.getStatus().equals(UserContactStatusEnum.FRIEND.getStatus())){
            log.error("当前用户不是好友关系，无法修改备注");
            throw new BusinessException(ExceptionBizCodeEnum.UPDATE_FAILED);
        }
        try{
            if(StringUtil.isEmpty(userContact.getRemark())){
                //新建储存remark
                Map<String, Object> userMap = new HashMap<>();
                userMap.put("userId", userContact.getUserId());
                userMap.put("remark", "");
                Map<String, Object> contactMap = new HashMap<>();
                contactMap.put("contactId", userContact.getContactId());
                contactMap.put("remark", "");
                //判断当前用户是userId还是contactID
                if(userContact.getUserId().equals(contactId)){
                    userMap.put("remark", remark);
                }else{
                    contactMap.put("remark", remark);
                }
                List<Map<String, Object>> mapList = new ArrayList<>();
                mapList.add(userMap);
                mapList.add(contactMap);
                //将Map转为json保存
                ObjectMapper objectMapper = new ObjectMapper();
                String jsonString = objectMapper.writeValueAsString(mapList);
                //储存jsonString
                userContact.setRemark(jsonString);
            }else{
                //将字符串转为List<HashMap>
                ObjectMapper objectMapper = new ObjectMapper();
                List<HashMap<String, Object>> remarkListMap = objectMapper.readValue(userContact.getRemark(), List.class);
                if(remarkListMap.size() != 2){
                    throw new BusinessException(ExceptionBizCodeEnum.UPDATE_FAILED);
                }
                //userId
                HashMap<String, Object> userMap = remarkListMap.get(0);
                HashMap<String, Object> contactMap = remarkListMap.get(1);
                //判断当前用户是userId还是contactID
                if(userContact.getUserId().equals(contactId)){
                    userMap.put("remark", remark);
                }else{
                    contactMap.put("remark", remark);
                }
                //将Map转为json保存
                String jsonString = objectMapper.writeValueAsString(remarkListMap);
                //储存jsonString
                userContact.setRemark(jsonString);
            }
        }catch (Exception e){
            log.error("更新备注失败", e);
            throw new BusinessException(ExceptionBizCodeEnum.UPDATE_FAILED);
        }
        this.baseMapper.updateById(userContact);
        return R.ok();
    }

    @Override
    public String addRemark(String contactId, String userId, String remark) throws BusinessException {
        try {
            //更新remark
            if (!StringUtil.isEmpty(remark)) {
                Map<String, Object> userMap = new HashMap<>();
                userMap.put("userId", userId);
                userMap.put("remark", "");
                Map<String, Object> contactMap = new HashMap<>();
                contactMap.put("contactId", contactId);
                contactMap.put("remark", remark);
                List<Map<String, Object>> updateList = new ArrayList<>();
                updateList.add(userMap);
                updateList.add(contactMap);
                //将Map转为json
                ObjectMapper objectMapper = new ObjectMapper();
                return objectMapper.writeValueAsString(updateList);
            }
            return null;
        }catch (Exception e){
            log.error("remark转换失败", e);
            return null;
        }
    }


    public record UserSimpleInfo(String userId, String beautifulNum, String personalSignature, Integer sex){}
    public record GroupSimpleInfo(String groupId,
                                  String beautifulNum,
                                  Integer currentNumber,
                                  String groupOwnerId,
                                  GroupNotice groupNotice){}

    @Override
    public R getGroupOrUserInfo(String contactId) {
        //判断contactId是用户还是群组
        UserContactTypeEnum typeEnum = UserContactTypeEnum.getPrefix(contactId);
        Map<String, Object> map = new HashMap<>();
        if(typeEnum == UserContactTypeEnum.USER){
            //查询用户信息
            UserInfoVO userInfo = userInfoMapper.selectUserById(contactId);
            if(userInfo != null){
                map.put("userOtherInfo", new UserSimpleInfo(userInfo.getUserId(),
                        userInfo.getUserInfoOther().getBeautifulNumber(),
                        userInfo.getPersonalSignature(), userInfo.getSex()));
            }

        }else {
            GroupInfo groupInfo = groupInfoMapper.selectById(contactId);
            if(groupInfo != null) {
                //查询最新的群公告信息
                GroupNotice groupNotice = groupNoticeMapper.selectNewestNoticeByGroupId(contactId);
                map.put("groupOtherInfo", new GroupSimpleInfo(groupInfo.getGroupId(),
                        groupInfo.getBeautifulNumber(),
                        groupInfo.getCurrentNumber(),
                        groupInfo.getGroupOwnerId(),
                        groupNotice));
            }

        }
        return R.ok().put(CodeConstant.RESULT_MSG, map);
    }

    public record SimpleGroupInfo(String groupId, String groupName, String groupAvatar){}
    @Override
    public R getAllGroupByUserId(String userId) {
        List<UserContact> userContacts = this.baseMapper.selectAllGroupByUserId(userId);
        List<String> groupIds = userContacts.stream().map(item -> {
            if (CommonUtil.isGroup(item.getContactId())) {
                return item.getContactId();
            } else if (CommonUtil.isGroup(item.getUserId())) {
                return item.getUserId();
            } else {
                return "";
            }
        }).toList();
        List<GroupInfo> groupInfos = groupInfoMapper.selectList(new LambdaQueryWrapper<GroupInfo>()
                .in(GroupInfo::getGroupId, groupIds));
        List<SimpleGroupInfo> simpleGroupInfos = groupInfos.stream().map(item -> new SimpleGroupInfo(item.getGroupId(), item.getGroupName(), item.getGroupAvatar())).toList();
        return R.ok().put(CodeConstant.RESULT_MSG, simpleGroupInfos);
    }

    @Override
    public String getRemark(String contactId, String remark) {
        try {
            //查询用户备注
            if(!StringUtil.isEmpty(remark)){
                ObjectMapper objectMapper = new ObjectMapper();
                List<HashMap<String, Object>> remarkListMap = objectMapper.readValue(remark, List.class);
                if(remarkListMap.size() != 2){
                    throw new BusinessException(ExceptionBizCodeEnum.REMARK_FORMAT_ERROR);
                }
                HashMap<String, Object> userMap = remarkListMap.get(0);
                HashMap<String, Object> contactMap = remarkListMap.get(1);
                if(userMap.get("userId").equals(contactId)){
                    return (String) userMap.get("remark");
                }
                if(contactMap.get("contactId").equals(contactId)){
                    return (String) contactMap.get("remark");
                }
                return "";
            }
            return "";
        }catch (Exception e){
            log.error("用户备注信息转换失败", e);
            return "";
        }
    }
}
